Starting in AP mode

Latest update: June 2015

This tutorial demonstrates how to start the FlashAir's wireless LAN in AP mode using iSDIO.

Overview

To start in AP mode, use the 'Establish' command regulated by iSDIO.

After the Establish command is issued, it can take about 20 seconds for the FlashAir to start up in AP mode.

To make sure the FlashAir is starting, use the status register.

We explained how to read the status register in Tutorial 3, but in this tutorial we aren't going to use the entire status register - we're only going to explain how to get the processing status after issuing a command.

Also, to run the Establish command properly, the FlashAir's wireless LAN should be unconnected. So, in this tutorial, we'll first run the Disconnect command to terminate any active wireless connections.

We're going to be adding to and modifying the source code from Tutorial 3.

About sequential ID

As previously described, it takes time to complete processing after a command is issued. We use a sequential ID to determine which command is the latest.

iSDIO's sequential ID is an unsigned 32bit integer. Every time a new command issued, increment the sequential ID by 1.

If the FlashAir itself changes wireless LAN settings (for example, due to a CGI command), please note that an iSDIO command may be issues and the sequential ID changed.

Because of this, you might want to create your own self-managed ID, and update it by getting the latest sequential ID after each command is issued. In this tutorial, to keep things simplified, we'll be reading the sequential ID shortly after starting and using a self-managed ID after that.

arduino_tutorial_04.ino (partially extracted)

uint32_t nextSequenceId = 0;

Issue an Establish command

The Establish command will start up the FlashAir's wireless LAN in AP mode. In the background, the FlashAir will also start up HTTP and DHCP servers.

For more information, please read SD Specifications Part E7 Wireless LAN Simplified Addendum Version 1.10 4.2.3 Estalibsh(ssid, networkKey, encMode)

To assemble the command data, the following information is required:

  • Command ID ( 3)
  • Sequential ID
  • The number of parameters ( 3)
  • Parameters
    • SSID
    • Network key (Password)
    • Security mode

arduino_tutorial_04.ino (partially extracted)

boolean iSDIO_establish(uint32_t sequenceId) {
  Serial.print(F("\nEstablish command: \n"));
  memset(buffer, 0, 512);
  uint8_t* p = buffer;
  p = put_command_header(p, 1, 0);
  p = put_command_info_header(p, 0x03, sequenceId, 3);
  p = put_str_arg(p, "sdiotest");
  p = put_str_arg(p, "12345678");
  p = put_u8_arg(p, 0x06);
  put_command_header(buffer, 1, (p - buffer));
  printHex(buffer, (p - buffer));
  return card.writeExtDataPort(1, 1, 0x000, buffer) ? true : false;
}
  • Lines 3-10:
    Assembling the command data we'll publish to the FlashAir.
  • Line 5:
    Use a helper function to make the command header. The last parameter contains the total length of the command data (in bytes). Because this will change, we're going to calculate it later.
  • Line 6:
    Use a helper function to make the command info header. Assign the establish command ID 0x03, sequential ID sequenceID, and the number of parameters 3.
  • Line 7:
    Writing the SSID. Using a helper function to write the string parameter.
  • Line 8:
    Similarly, writing the network key.
  • Line 9:
    Similarly, writing the security mode. Here, we're assigning 0x06 for WPA2-PSK and AES. Please see the specification for other values. We also use a helper function to write our data.
  • Line 10:
    All data was written, and now that we have the number of bytes we'll rewrite the command header.
  • Line 11:
    Dumping command data to confirm it was made successfully. Please see sample code fpr printHex() function.
  • Line 12:
    Writing data to the FlashAir.

Check the command processing status

To check the command processing status, we can read the command response status from iSDIO.

Command response status (abstracted from SD Specifications Part E7 iSDIO Simplifed Specification Version 1.10)

Command response status

The most important parts are iSDIO command sequence id and Response Status. Make sure the iSDIO command sequence id is same as the sequence ID we want to check. After making sure the IDs are identical, check the processing status with the Response Status.

In addition, the iSDIO standard allows for up to eight commands to be issued at a time - however FlashAir supports only one, so we only need to read address 0x440.

Make a function that waits for our command to end.

arduino_tutorial_04.ino (partially extracted)

boolean iSDIO_waitResponse(uint32_t sequenceId) {
  Serial.print(F("\nWaiting response "));
  uint8_t prev = 0xFF;
  for (int i = 0; i < 20; ++i) {
    memset(buffer, 0, 0x14);

    // Read command response status.
    if (!card.readExtMemory(1, 1, 0x440, 0x14, buffer)) {
      return false;
    }

    uint8_t resp = get_u8(buffer + 8);
    if (sequenceId == get_u32(buffer + 4)) {
     if (prev != resp) {
        switch (resp) {
          case 0x00:
            Serial.print(F("\n  Initial"));
            break;
          case 0x01:
            Serial.print(F("\n  Command Processing"));
            break;
          case 0x02:
            Serial.println(F("\n  Command Rejected"));
            return false;
          case 0x03:
            Serial.println(F("\n  Process Succeeded"));
            return true;
          case 0x04:
            Serial.println(F("\n  Process Terminated"));
            return false;
          default:
            Serial.print(F("\n  Process Failed "));
            Serial.println(resp, HEX);
            return false;
        }
        prev = resp;
      }
    }
    Serial.print(F("."));
    delay(1000);
  }
  return false;
}
  • Line 8:
    Reading command response status register.
  • Line 13:
    Making sure the sequential IDs are identical.
  • Lines 15-35:
    Checking response status. When the processing is finished, the status will become "Process Succeeded" (0x03).
  • Line 39:
    Execute this check every second.

Issue a Disconnect command

The Disconnect command terminates the wireless LAN. It will also stop the HTTP and DHCP servers.

For more information, please read SD Specifications Part E7 Wireless LAN Simplified Addendum Version 1.10 4.2.7 Disconnect(ssid, networkKey, encMode)

To assemble the command data, the following information is required:

  • Command ID ( 7)
  • Sequential ID
  • The number of parameter ( 0)

arduino_tutorial_04.ino (partially extracted)

boolean iSDIO_disconnect(uint32_t sequenceId) {
  Serial.print(F("\nDisconnect command: \n"));
  memset(buffer, 0, 512);
  uint8_t* p = buffer;
  p = put_command_header(p, 1, 0);
  p = put_command_info_header(p, 0x07, sequenceId, 0);
  put_command_header(buffer, 1, (p - buffer));
  printHex(buffer, (p - buffer));
  return card.writeExtDataPort(1, 1, 0x000, buffer) ? true : false;
}

Main program

The main program is going to be interactive.

Depending on the number input from the Arduino's serial terminal, we'll either run "Status display", "Disconnect", or "Establish".

arduino_tutorial_04.ino (partially extracted)

void loop() {
  if (!iSDIO_status()) {
    Serial.println(F("\nFailed to read status."));
  }

  Serial.print(F("\n0. Show status"));
  Serial.print(F("\n1. Disconnect"));
  Serial.print(F("\n2. Establish"));
  Serial.print(F("\n\nCommand? (next sequence id = "));
  Serial.print(nextSequenceId, DEC);
  Serial.println(F(")"));

  while (Serial.available() == 0);
  char command = Serial.read();

  switch (command - '0') {
    case 0 :
      break;
    case 1 :
      if (iSDIO_disconnect(nextSequenceId) &&
          iSDIO_waitResponse(nextSequenceId)) {
        Serial.println(F("\nSuccess."));
      } else {
        Serial.print(F("\nFailed or waiting. errorCode="));
        Serial.println(card.errorCode(), HEX);
      }
      nextSequenceId++;
      break;
    case 2 :
      if (iSDIO_establish(nextSequenceId) &&
          iSDIO_waitResponse(nextSequenceId)) {
        Serial.println(F("\nSuccess."));
      } else {
        Serial.print(F("\nFailed or waiting. errorCode="));
        Serial.println(card.errorCode(), HEX);
      }
      nextSequenceId++;
      break;
    default :
      Serial.println(F("\nUnknown command."));
      break;
  }
}
  • Line 2:
    Show the status.
  • Lines 6-11:
    Show the executable command and next sequential ID.
  • Lines 13-14:
    Waiting for input.
  • Lines 16-42:
    Run a command according to the input number.

Since the status display was included in the loop() function, delete it from the setup() function.

arduino_tutorial_04.ino (partially extracted)

void setup() {
  // Initialize UART for message print.
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  // Initialize SD card.
  Serial.print(F("\nInitializing SD card..."));  
  if (card.init(SPI_HALF_SPEED, chipSelectPin)) {
    Serial.print(F("OK"));
  } else {
    Serial.print(F("NG"));
    abort();
  }

  // Read the previous sequence ID.
  if (card.readExtMemory(1, 1, 0x420, 0x34, buffer)) {
    if (buffer[0x20] == 0x01) {
      nextSequenceId = get_u32(buffer + 0x24);
      iSDIO_waitResponse(nextSequenceId);
      nextSequenceId++;
    } else {
      nextSequenceId = 0; 
    }
  } else {
    Serial.println(F("\nFailed to read status."));
    nextSequenceId = 0; 
  }
}
  • Lines 17-29:
    Reading last used sequential ID. Also waiting for completion if the last command is still running.

Execution result

Initializing SD card...OK
Wait for response 
  Process Succeeded

Read iSDIO Status Register
 == iSDIO Status Registers == 
 [0400h] Command Write Status: 
... (snip) ...
 [0440h] Command Response Status #1: id = 3, sequence id = 1, status = Process Succeeded
... (snip) ...
 [0506h] WLAN: No Scan, No WPS, Group Client, AP, Infrastructure, No Connection, 
... (snip) ...
 [0550h] IP Address: 192.168.0.1
... (snip) ...

0. Show status
1. Disconnect
2. Establish

Command? (next sequence id = 2)

The current status is displayed at the start, in this example the FlashAir started in AP mode.

Input your command in the box at the top of serial terminal in the Arduino IDE.

1 Input Enter.

Disconnect command: 

00: 01010000180000000000000000000700
01: 0700000000000000

Wait for response 
  Command Processing.
  Process Succeeded

Success.

Read iSDIO Status Register
... (snip) ...
 [0440h] Command Response Status #1: id = 7, sequence id = 2, status = Process Succeeded
... (snip) ...
 [0506h] WLAN: No Scan, No WPS, Group Client, STA, Initial, No Connection, 
... (snip) ...
 [0550h] IP Address: 0.0.0.0
... (snip) ...

Command? (next sequence id = 3)

Line 14 indicates that a disconnect command was issued and completed (Disconnect command ID is 7), shows the assigned sequential ID, and status ( Process Succeeded). You can tell that the wireless LAN is disconnected because it's set to STA mode, and the IP Address is 0.0.0.0.

Lines 3 to 4 are command data. Check them if something goes wrong.

Next, lets start AP mode.

Input 2, in the serial terminal box.

Establish command: 

00: 01010000380000000000000000000300
01: 0800000003000000080000007364696F
02: 74657374080000003132333435363738
03: 0100000006000000

Wait for response 
  Command Processing.....
  Process Succeeded

Success.

Read iSDIO Status Register
... (snip) ...
 [0440h] Command Response Status #1: id = 3, sequence id = 3, status = Process Succeeded
... (snip) ...
 [0506h] WLAN: No Scan, No WPS, Group Client, AP, Infrastructure, No Connection, 
 [0508h] SSID: sdiotest
 [0528h] Encryption Mode: WPA2-PSK and AES
 [0529h] Signal Strength: 0
 [052Ah] Channel: 11
 [0530h] MAC Address: E8E0B758A7FB
 [0540h] ID: 
 [0550h] IP Address: 192.168.0.1
 [0554h] Subnet Mask: 255.255.255.0
 [0558h] Default Gateway: 192.168.0.1
 [055Ch] Preferred DNS Server: 192.168.0.1
 [0560h] Alternate DNS Server: 0.0.0.0
... (snip) ...

An Establish command (ID 3) has been executed. ( Line 16)

You can see that the FlashAir started in AP mode because the WLAN status is AP and the IP Address is 192.168.0.1.

Sample code

arduino_tutorial_04.zip (24KB)

All sample code on this page is licensed under BSD 2-Clause License.